#!/usr/bin/env python

"""
Authors:
Oto Brglez - <otobrglez@gmail.com>
Kasun Herath - <kasunh01@gmail.com>

This is experimental Google Buzz API.
Google Buzz API Specification as this time is still poor.

URL: http://code.google.com/p/mbuzz/
"""

import urllib2
import xml.etree.ElementTree as ET
from django.utils.encoding import smart_str, smart_unicode
import pdb	# only when debugging

"""This class is used for fetching and posting updates
"""
class Buzz:
	"""Profile name/ Profile ID
	"""
	_profile = None
	_entry_list = []


	"""Simple init. It only takes profile ID as argument
	"""
	def __init__(self, profile):
		self._profile = profile

	"""This function returns updates
	"""
	def getUpdates(self):
		if(self._profile == None):
			raise BuzzException("Missing profile name!");

		request = urllib2.Request("http://buzz.googleapis.com/feeds/"+self._profile+"/public/posted");
		response = urllib2.urlopen(request)
		tree = ET.XML(response.read())

		self._entry_list = []
		for t in tree.findall(Namespaces.NS_ATOM + "entry"):
			self._entry_list.append( BuzzEntry(t, Namespaces.NS_ATOM))
	
		return self._entry_list

"""This class is used for exceptions coused by Buzz class.
"""
class BuzzException(Exception):
	"""Constructor
	"""
	def __init__(self, value):
		self.parameter = value
	
	"""Converting Exception to string
	"""
	def __str__(self):
		return repr(self.parameter)
	
"""This class represent single entry
"""
class BuzzEntry(object):
	_element = None
	_NS = ""

	"""Constructor for Buzz entry
	"""
	def __init__(self, element, ns=None):
		self._element = element
		self._NS = ns or Namespaces.NS_ATOM
	
	"""Simple output of buzz
	"""
	def __str__(self):
		try:
			return smart_str( (self._element.findall(self._NS + "summary")[0]).text )
		except AttributeError:
			raise BuzzException("Attribute error!"); # Missing additional info!

	"""Return specific attribute
	"""
	def __getitem__(self, key, NS=None):
		NS = NS or self._NS
		try:
			return ( (self._element.findall(NS + key)[0]) )
		except IndexError:
			raise BuzzException("No value found!")
	
	"""Return the Iterator
	"""
	def __iter__(self):
		self._child_elements = []
		
		for child in self._element.getchildren():
			if child.tag.find(Namespaces.NS_ATOM) != -1:
				self._child_elements.append(child)

		self._count = 0
		return self

	"""Return items
	"""
	def next(self):
		if self._count == len(self._child_elements):
			raise StopIteration
		child = self._child_elements[self._count]
		self._count = self._count + 1
		utils = Utils()
		return utils.getlocalFromQName(child.tag)
	
	"""Does Buzz have any comments?
	"""
	def hasComments(self):
		num_of_comments = self.__getitem__("total", Namespaces.NS_thr).text
		return num_of_comments != '0'
	
	"""Return the number of comments per buzz
	"""
	def getNumberOfComments(self):
		return self.__getitem__("total", Namespaces.NS_thr).text

"""Class to hold different Namespaces
"""	
class Namespaces:
	# Default namespace is Atom
	NS_ATOM = "{http://www.w3.org/2005/Atom}"
	# Namespace used for thread
	NS_thr = "{http://purl.org/syndication/thread/1.0}" 	
	
"""
Utilities
"""            
class Utils:
    def getlocalFromQName(self, qname):
    	"""Method to extract local name from qname
    	"""
        try:
            start = qname.index('}')
            end = len(qname)
            local = qname[start+1:end]
            return local
        except ValueError:
            raise BuzzException('Wrong formatted QName')
		
if __name__ == "__main__":

	buzz = Buzz("otobrglez")
	
	# Retrive all buzzes and show 10 of them
	for update in buzz.getUpdates()[:5]:
		# Access to google buzz id
		print "Buzz ID : ", update["id"].text

		# Buzz summary (in txt format)
		print update["summary"].text

		# Author name is part of "author"
		#TODO: Shorten this code 
		#print "By ", update["author"].findall(update._NS + "name")[0]
		print "By ", update["author"].findall(update._NS + "name")[0].text
		
		# Number of comments per current buzz
		print 'Comments', update.getNumberOfComments()
	
	#using the iterator to get info from updates
	print '--------------using iterator------------------------'
	
	for update in buzz.getUpdates()[:1]:
		for info in update:
			print info + " - " + str(update[info].text)
	
